package com.ossean.projectmanager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

import com.ossean.projectmanager.hotwords.InsertHotwords;
import com.ossean.projectmanager.hotwords.MapSort;
import com.ossean.projectmanager.hotwords.StringHandler;
import com.ossean.projectmanager.hotwords.UpdateTagsAndTaggings;
import com.ossean.projectmanager.lasttabledao.OpenSourceProjectDao;
import com.ossean.projectmanager.lasttabledao.PointersDao;
import com.ossean.projectmanager.lasttabledao.RelativeMemoDao;
import com.ossean.projectmanager.lasttabledao.RelativeMemoToOpenSourceProjectDao;
import com.ossean.projectmanager.lasttabledao.TagDao;
import com.ossean.projectmanager.lasttabledao.TaggingsDao;
import com.ossean.projectmanager.model.Hotword;
import com.ossean.projectmanager.model.OpenSourceProject;
import com.ossean.projectmanager.model.RelativeMemo;
import com.ossean.projectmanager.model.RelativeMemoToOpenSourceProject;

@Component
public class HotwordsMain {
	Logger logger = Logger.getLogger(this.getClass());
	@Resource
	private PointersDao pointersDao;
	@Resource
	private OpenSourceProjectDao ospDao;
	@Resource
	private RelativeMemoToOpenSourceProjectDao memoToOspDao;
	@Resource
	private TaggingsDao taggingsDao;
	@Resource
	private RelativeMemoDao memoDao;
	@Resource
	private TagDao tagsDao;
	@Qualifier("updatetagsandtaggings")
	@Autowired
	private UpdateTagsAndTaggings updateClass;
	@Qualifier("inserthotwords")
	@Autowired
	private InsertHotwords insertClass;
	private static String sourceTableName = "open_source_projects";
	private static String targetTableName = "hot_words";
	
	private static int batchSize = 10;// 一次处理项目数量
	public void start(){
		while(true){
			//读取断点位置
			int startId = 1;
			try {
				startId = pointersDao.readPointer(sourceTableName, targetTableName);
			} catch (Exception e){
				//表示还没有该记录
				pointersDao.insertPointer(sourceTableName, targetTableName);
			}
			//根据断点位置和批处理数量读取项目对象列表
			List<OpenSourceProject> projects = ospDao.getProjectsByBatch(startId, batchSize);
			if(projects.size() == 0){
				//如果没有独处项目信息 表示没有需要处理的项目
				logger.info("no projects! Sleep 3600s");
				try {
					Thread.sleep(3600*1000L);
					continue;
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			for(OpenSourceProject project:projects){
				//循环处理所有的项目
				logger.info("匹配项目:" + project.getName() + " id:" + project.getId());
				//读取relative_memo_to_open_source_projects表中当前项目对应的帖子
				int prjId = project.getId();
				List<RelativeMemoToOpenSourceProject> mtps = memoToOspDao.getHighWeightMatchResult(prjId, getTargetTable(prjId));
				//定义存储标签name和标签权重的map 每个project一个map对象
				Map<String, Float> tagWeightMap = new LinkedHashMap<String,Float>();
				//定义存储标签name和标签词频的map 每个project一个map对象
				Map<String, Integer> tagCountMap = new HashMap<String, Integer>();
				//遍历每一个关联结果 即遍历每一个关联的帖子
				for(RelativeMemoToOpenSourceProject item:mtps){
					//读取帖子id
					int memoId = item.getRelative_memo_id();
					//获取RelativeMemo对象
					RelativeMemo memo = memoDao.getById(memoId);
					//将RelativeMemos对象中的tags属性转换成List<String>
					List<String> memoTagList = new ArrayList<String>();
					try{
						memoTagList = StringHandler.changeTagsToTagList(memo.getTags());
					}catch(Exception e){
						//logger.info("没有找到对应的tags标签 memo_id:" + memoId);
						continue;
					}
					//循环遍历每个tagName 将对应的权重计算出来 得到最终的map
					for(String tagName:memoTagList){
						if(tagWeightMap.containsKey(tagName)){
							//表示map中已经存在该标签 需要将原来标签的权重取出并加上相应的taggings表中记录的匹配权重
							tagWeightMap.put(tagName, tagWeightMap.get(tagName) + item.getMatch_weight());
							tagCountMap.put(tagName, tagCountMap.get(tagName) + 1);
						}else{
							//表示map中没有该标签名
							tagWeightMap.put(tagName, item.getMatch_weight());
							tagCountMap.put(tagName,1);
						}
					}
				}
				//将map根据值从大到小排序
				tagWeightMap = MapSort.sort(tagWeightMap);
				//构造hotwords的List
				List<Hotword> hotwordsList = new ArrayList<Hotword>();
				Set<String> tagNames = tagWeightMap.keySet();
				Iterator<String> iterator = tagNames.iterator(); 
				int count_hotwords = 0;
				while(iterator.hasNext() && count_hotwords < 20){
					String tagName = iterator.next();//读取标签的名字
					Hotword hotwords = new Hotword();
					hotwords.setOsp_id(project.getId());
					hotwords.setName(tagName);
					hotwords.setWeight(tagWeightMap.get(tagName));
					count_hotwords++;
					hotwordsList.add(hotwords);
				}
				
				//读取该项目的tags属性并转换成List
				List<String> projectTagList = StringHandler.changeTagsToTagList(project.getTags());
				//记录需要修改disagree_num的标签名
				List<String> updateDisagreeNumTagNameList = new ArrayList<String>();
				if(projectTagList.size() < 10){
					//表示如果项目标签数量小于10 向里面添加5填新的标签记录
					//遍历项目关联的所有标签
					Set<String> keys = tagWeightMap.keySet();
					Iterator<String> it = keys.iterator();
					int count = 0;//用于对新添加到项目中的标签进行计数
					//最多增加5个新的标签 最多增加到10个
					while(it.hasNext() && count < 5){
						String tagName = it.next();//取出标签的名字
						if(StringHandler.isTagExist(tagName, projectTagList)){
							//表示当前关联到的标签在项目标签中存在 需要对taggings表中disagree_num增加该标签出现的词频
							updateDisagreeNumTagNameList.add(tagName);//将需要修改的标签名先存储到列表中 在事物处理的时候统一处理
							continue;
						}else{
							//表示当前关联到的标签在项目原标签中不存在
							projectTagList.add(tagName);//将新标签添加到项目标签列表中
							count++;//每添加一个新标签 count计数器加1
						}
					}
					//如果count > 0 表示tags属性需要更新，taggings需要插入记录 同时需要向热词表中插入20条数据
					if(count > 0){
						String tagsNew = StringHandler.changeTagListToTags(projectTagList);
						logger.info("正在进行更新项目标签信息和taggings表信息操作，请勿中断程序");
						updateClass.update(project, projectTagList, tagsNew, count, sourceTableName, targetTableName, hotwordsList, updateDisagreeNumTagNameList, tagCountMap);
					}
					else{
						//表示没有新增的标签 只需要向热词表中添加20条热词
						insertClass.insert(hotwordsList, sourceTableName, targetTableName, project.getId() + 1, updateDisagreeNumTagNameList, tagCountMap, project);
						logger.info("当前项目" + project.getName() + "没有标签更新操作，只插入了热词和更新disagree_num标签");
					}
				}
				else{
					//表示项目已经存在10条记录 需要再添加3个标签 已经存在的标签不算在3个内
					//遍历项目关联的所有标签
					Set<String> keys = tagWeightMap.keySet();
					Iterator<String> it = keys.iterator();
					int count = 0;//用于对新添加到项目中的标签进行计数
					//最多增加5个新的标签 最多增加到10个
					while(it.hasNext() && count < 3){
						String tagName = it.next();//取出标签的名字
						if(StringHandler.isTagExist(tagName, projectTagList)){
							//表示当前关联到的标签在项目标签中存在 需要对taggings表中disagree_num增加该标签出现的词频
							updateDisagreeNumTagNameList.add(tagName);//将需要修改的标签名先存储到列表中 在事物处理的时候统一处理
							continue;
						}else{
							//表示当前关联到的标签在项目原标签中不存在
							projectTagList.add(tagName);//将新标签添加到项目标签列表中
							count++;//每添加一个新标签 count计数器加1
						}
					}
					//如果count > 0 表示tags属性需要更新，taggings需要插入记录 同时需要向热词表中插入20条数据
					if(count > 0){
						String tagsNew = StringHandler.changeTagListToTags(projectTagList);
						logger.info("正在进行更新项目标签信息和taggings表信息操作，请勿中断程序");
						updateClass.update(project, projectTagList, tagsNew, count, sourceTableName, targetTableName, hotwordsList, updateDisagreeNumTagNameList, tagCountMap);
					}
					else{
						//表示没有新增的标签 只需要向热词表中添加20条热词
						insertClass.insert(hotwordsList, sourceTableName, targetTableName, project.getId() + 1, updateDisagreeNumTagNameList, tagCountMap, project);
						logger.info("当前项目" + project.getName() + "只插入了热词和更新disagree_num标签");
					}
					insertClass.insert(hotwordsList, sourceTableName, targetTableName, project.getId() + 1, updateDisagreeNumTagNameList, tagCountMap, project);
					logger.info("当前项目" + project.getName() + "只插入了热词和更新disagree_num标签");
				}
			}
		}
	}
	
	/**
	 * get the match result table's name
	 * @param osp_id
	 * @return
	 */
	public static String getTargetTable(int ospId){
		String targetTableName = "";
		if(ospId >= 770000){
			targetTableName = "relative_memo_to_open_source_projects_70";
		}
		else{
			int a = 1 + ospId/11000;
			targetTableName = "relative_memo_to_open_source_projects_" + a;
		}
//		if (osp_id < 500) {
//			targetTableName = "relative_memo_to_open_source_projects_1";
//		}
//		else if (osp_id >= 500 && osp_id < 1000) {
//			targetTableName = "relative_memo_to_open_source_projects_2";
//		}
//		else if (osp_id >= 1000 && osp_id < 1500) {
//			targetTableName = "relative_memo_to_open_source_projects_3";
//		}
//		else if (osp_id >= 1500 && osp_id < 2000) {
//			targetTableName = "relative_memo_to_open_source_projects_4";
//		}
//		else if (osp_id >= 2000 && osp_id < 3000) {
//			targetTableName = "relative_memo_to_open_source_projects_5";
//		}
//		else if (osp_id >= 3000 && osp_id < 5000) {
//			targetTableName = "relative_memo_to_open_source_projects_6";
//		}
//		else if (osp_id >= 5000 && osp_id < 7500) {
//			targetTableName = "relative_memo_to_open_source_projects_7";
//		}
//		else if (osp_id >= 7500 && osp_id < 10000) {
//			targetTableName = "relative_memo_to_open_source_projects_8";
//		}
//		else if (osp_id >= 10000 && osp_id < 310000) {
//			int a = 7 + osp_id/5000;
//			targetTableName = "relative_memo_to_open_source_projects_" + a;
//		}
//		else if (osp_id >= 310000) {
//			targetTableName = "relative_memo_to_open_source_projects_70";
//		}
		return targetTableName;
		//return "relative_memo_to_open_source_projects";
	}
	
	public static void main(String[] args){
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/applicationContext*.xml");
		HotwordsMain mainClass = applicationContext.getBean(HotwordsMain.class);
		mainClass.start();
	}

}
